home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- These C++ classes are copyright 1990, by William Herrera.
- All those who put this code or its derivatives in a commercial product MUST
- mention this copyright in their documentation for users of the products in
- which this code or its derivative classes are used. Otherwise, this code
- may be freely distributed and freely used for any purpose.
-
- Enhancements: 1991 by David Orme
- * General cleanup.
- - I/O now takes advantage of C++ overloading.
- - Serial port I/O functionality now only in Serial class.
- - Modem functionality now only in Modem class.
- * Possible to easily implement file Xfr prots now.
- * CCITT CRC-16 class added -- 2-20-1991
- * BIOS Timer class added -- 2-22-1991
- * Optional timeout on all input routines added -- 2-25-1991
-
- ***************************************************************************/
-
- // file comports.cpp defines various uart classes.
-
- #include <stdlib.h>
-
- #include "comports.hpp"
-
- static const int insize = 1024;
- static const int outsize = 4096;
-
- // C++ 2.0 requires that static members be declared globally...
-
- COM1 * COM1::this_ptr;
- COM2 * COM2::this_ptr;
- COM3 * COM3::this_ptr;
- COM4 * COM4::this_ptr;
-
-
- #ifdef __TURBOC__
-
- #define DEFINE_COMX(COM, x, driver) \
- CharQueue * COM##x::inq = new CharQueue(insize); \
- CharQueue * COM##x::outq = new CharQueue(outsize); \
- DRIVER COM##x::driver = driver##x; \
- COM##x::COM##x() \
- { \
- this_ptr = this; \
- DoIfNoCarrier = DoNothing; \
- DoOnRing = DoNothing; \
- if(RegisterDriver(##x, driver##x) != 0) \
- exit(1); \
- } \
- COM##x::~COM##x() \
- { \
- if(RestoreDriver(##x) != 0) \
- exit(1); \
- } \
- void COM##x::SetDoIfNoCarrier(void (*f)()) \
- { \
- DoIfNoCarrier = f; \
- } \
- void COM##x::SetDoOnRing(void (*f)()) \
- { \
- DoOnRing = f; \
- } \
- void COM##x::FlushOutput() \
- { while (!outq->IsEmpty()) {;} } \
- void COM##x::SendChar(char ch) \
- { \
- while(outq->IsFull()) \
- ; /* wait til queue transmitted by driver */ \
- outq->Add(ch); \
- SetIER_Transmit(true); \
- } \
- int COM##x::GetChar() \
- { \
- return inq->Get(); \
- /* remember, empty charqueue flag is -1. */ \
- } \
- \
- void interrupt driver##x(...) \
- { \
- /* driver for comm interrupt. */ \
- COM##x * cptr = COM##x::this_ptr; \
- com_interrupt_t i; \
- while((i = cptr->GetIntrType()) != NONE_PENDING) \
- { \
- disable(); /* don't let another come in */ \
- switch((int)i & 0xFF) \
- { \
- case (int)TRANSMIT_READY : \
- if(COM##x::outq->IsEmpty()) \
- cptr->SetIER_Transmit(false); \
- else \
- cptr-> \
- TransmitChar(COM##x::outq->Get()); \
- break; \
- case (int)RECEIVE_READY: \
- if(!COM##x::inq->IsFull()) \
- COM##x::inq-> \
- Add(cptr->ReceiveChar()); \
- break; \
- case (int)NO_CARRIER: \
- (*cptr->DoIfNoCarrier)(); \
- break; \
- case (int)RING: \
- (*cptr->DoOnRing)(); \
- break; \
- default: \
- /* all others here. the function */ \
- /* GetIntrType() should have already */ \
- /* cleaned up the other interrupt flags. */ \
- break; \
- } \
- enable(); /* other interrupts now ok */ \
- } \
- outportb( 0x20, 0x20); \
- }
-
-
-
-
- #else ifdef __ZTC__
-
- #define DEFINE_COMX(COM, x, driver) \
- CharQueue * COM##x::inq = new CharQueue(insize); \
- CharQueue * COM##x::outq = new CharQueue(outsize); \
- DRIVER COM##x::driver = driver##x; \
- COM##x::COM##x() \
- { \
- this_ptr = this; \
- DoIfNoCarrier = DoNothing; \
- DoOnRing = DoNothing; \
- if(RegisterDriver(##x, driver##x) != 0) \
- exit(1); \
- } \
- COM##x::~COM##x() \
- { \
- if(RestoreDriver(##x) != 0) \
- exit(1); \
- } \
- void COM##x::SetDoIfNoCarrier(void (*f)()) \
- { \
- DoIfNoCarrier = f; \
- } \
- void COM##x::SetDoOnRing(void (*f)()) \
- { \
- DoOnRing = f; \
- } \
- void COM##x::FlushOutput() \
- { while (!outq->IsEmpty()) {;} } \
- void COM##x::SendChar(char ch) \
- { \
- while(outq->IsFull()) \
- ; \
- outq->Add(ch); \
- SetIER_Transmit(true); \
- } \
- int COM##x::GetChar() \
- { \
- return inq->Get(); \
- } \
- \
- int driver##x(INT_DATA *pd) \
- { \
- COM##x * cptr = COM##x::this_ptr; \
- com_interrupt_t i; \
- while((i = cptr->GetIntrType()) != NONE_PENDING) \
- { \
- disable(); /* don't let another come in */ \
- switch((int)i & 0xFF) \
- { \
- case (int)TRANSMIT_READY : \
- if(COM##x::outq->IsEmpty()) \
- cptr->SetIER_Transmit(false); \
- else \
- cptr-> \
- TransmitChar(COM##x::outq->Get()); \
- break; \
- case (int)RECEIVE_READY: \
- if(!COM##x::inq->IsFull()) \
- COM##x::inq-> \
- Add(cptr->ReceiveChar()); \
- break; \
- case (int)NO_CARRIER: \
- (*cptr->DoIfNoCarrier)(); \
- break; \
- case (int)RING: \
- (*cptr->DoOnRing)(); \
- break; \
- default: \
- break; \
- } \
- enable(); /* other interrupts now ok */ \
- } \
- outportb( 0x20, 0x20); \
- return 1; \
- }
-
-
- #endif
-
- // To define up to four com ports, you should
- // declare one or more of the following statements:
-
- DEFINE_COMX(COM, 1, driver)
- DEFINE_COMX(COM, 2, driver)
- DEFINE_COMX(COM, 3, driver)
- DEFINE_COMX(COM, 4, driver)
-
-